[Android]別スレッドで処理を実行する方法(Thread、AsyncTask) – fineblue206.net

您所在的位置:网站首页 thread android [Android]別スレッドで処理を実行する方法(Thread、AsyncTask) – fineblue206.net

[Android]別スレッドで処理を実行する方法(Thread、AsyncTask) – fineblue206.net

#[Android]別スレッドで処理を実行する方法(Thread、AsyncTask) – fineblue206.net| 来源: 网络整理| 查看: 265

Androidはメインスレッド(UIスレッドとも呼ばれる)でユーザの操作を受け付けたり画面の描画処理を行っている。そのため外部との通信や大量のデータ処理等、時間のかかる処理をメインスレッドで走らせるとアプリが無反応になってしまう。あまりに処理時間が長いとOSがアプリを強制終了させてしまうこともあるので重たい処理は別スレッドで実行するよう推奨されている

そんなわけで別スレッドで処理を実行する方法を記しておく。

Threadクラスを継承する方法

Threadクラスを継承したクラスを作成し、別スレッドで実行したい非同期処理をrun()メソッドをオーバーライドして記述する。

class ThreadSleep1Second extends Thread { @Override public void run() { sleep(1000); //1秒待機 } }

上の例は1秒間待機するだけのクラスだが、通常はrun()メソッドにもっと長いコードを書くことになる。

クラスの定義ができれば、そのインスタンスを作成し、start()メソッドを呼び出す。run()メソッドを直接呼ぶと、別スレッドではなくメインスレッドで実行されてしまうので注意が必要だ。

ThreadSleep1Second thread1 = new ThreadSleep1Second(); thread1.start();

上の例のThreadSleep1Secondクラスは1秒待機したらそのまま何もせずに終了してしまう。処理が終了したことをメインスレッドに通知するにはHandlerクラスを使う。下の例は1秒待機した後にToastでメッセージを表示している。

class ThreadSleep1Second extends Thread { private Context context; public ThreadSleep1Second (Context context) { this.context = context; } @Override public void run() { sleep(1000); //1秒待機 Handler mainThreadHandler = new Handler(Looper.getMainLooper()); mainThreadHandler.post(new Runnable() { @Override public void run() { //メインスレッドで実行する処理 Toast.makeText(this.context,"1 second", Toast.LENGTH_SHORT).show(); } }); } }

ネットを検索するとHandlerをメインスレッドで作成して、コンストラクタの引数で渡している例があるが、ローカル変数でもインスタンス作成時にメインスレッドのLooper(Looper.getMainLooper())を指定することでメインスレッドにMessageやRunnableを送ることができる。

Handlerの使い方はこちらのサイトが参考になるので見て欲しいhttps://qiita.com/8yabusa/items/f8c9bb7eb81175c49e97http://d.hatena.ne.jp/sankumee/20120329/1333021847

AsyncTaskクラスを継承する方法

Threadクラスでスレッドを作ると、メインスレッドとのやり取りにHandler、Runnable、Messageといったクラスを組み合わせて記述しなければならない。そして大抵の場合、無名クラスを多用してコードがあちこちに散らばってしまい、可読性が悪くなる。そういった面倒をなくすためにパッケージ化したのがAsyncTaskクラスである。

■AsyncTaskに用意されている主なメソッドonPreExecute()doInBackgroundメソッドの実行前にメインスレッドで実行される。

doInBackground()メインスレッドとは別のスレッドで実行される。ThreadクラスのRun()メソッドに相当する。このメソッドだけは必ず実装する必要がある。

onProgressUpdate()メインスレッドで実行される。非同期処理の進行状況をプログレスバーで表示したい時などに使う。

onPostExecute()doInBackgroundメソッドの実行後にメインスレッドで実行さる。doInBackgroundメソッドの戻り値をこのメソッドの引数として受け取り、その結果を画面に反映させることができる。

前出例のThreadSleep1Secondクラスと同じ内容をAsyncTaskクラスを使って書くと次のようになる

class AsyncSleep1Second extends AsyncTask{ private Context context; public AsyncSleep1Second (Context context) { this.context = context; } @Override protected void onPreExecute() { //何もしない } @Override protected Void doInBackground(Void... voids){ Thread.sleep(1000); //1秒待機 return null; } @Override protected void onPostExecute(Void aVoid) { Toast.makeText(this.context, "1 second", Toast.LENGTH_SHORT).show(); } }

このように別スレッドで実行される処理の他に、前処理や後処理も同じクラスの中に書くことができる。

これのインスタンスを作成し、execute()メソッドを呼ぶと別スレッドで非同期処理が実行される。

AsyncSleep1Second task = new AsyncSleep1Second(this); task.execute();

ジェネリクスの指定はとなっているが、意味は次の通り。第一変数doInBackground()の引数の型。execute()メソッドの引数が配列で渡される値が一つだけの時はインデックス0で取得する

第二変数onProgressUpdate()の引数の型

第三変数onPostExecute()の引数の型doInBackground()の戻り値がonPostExecute()の引数となる

例では引数を使用していないのですべてVoid型になっている。

個人的にはAsyncTaskが簡潔にコードを記述できるので多用しているが、スレッド間で複雑な情報のやり取りが発生する場合はThreadクラスを使っている。どちらのやり方も覚えておいて損はない。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3